<html>
<head>
<title>Clay
</title>
</head>
<body BGCOLOR="#FFFFFF">
<FONT FACE="ariel,helvetica">

<H2>TeamBots<SUP><font size=-3>TM</font></SUP> Software Package: Clay</H2>

<b>Welcome</b><BR>
Welcome to the Clay information page.
This documentation is also included with the TeamBots distribution in
EDU/gatech/cc/is/clay/index.html .

<P>
Jump to the <a href="../../../../../Docs/Package-EDU.gatech.cc.is.clay.html">Clay Package Index</a>

<P>

<b>Introduction</b><BR>

Clay is a group of Java classes that can be easily combined
to create behavior-based robot control systems.
Clay takes advantage of Java syntax to facilitate combining,
blending and abstraction of behavior.
Clay can be used to create simple reactive systems or
complex hierarchical configurations with learning and memory.

<P>

<b>Configuring Behavior with Clay</b><BR>

The basic building block in Clay is a <b>node</b>.
There are two important phases in a node's life: intialization
and runtime.
Most nodes have only two methods, corresponding to
these phases: the constructor, used for
initialization; and Value(), called repeatedly at runtime.
<P>
Nodes often have other nodes embedded within them (e.g. an
avoid_obstacle node typically has a detect_obstacle node embedded within it).
The embedding is specified at initialization
time using the node's constructor.  Here is an example
of how we'd embed one node in another:

<PRE>
<B>detect_obstacles</B> = new va_Obstacles_r(abstract_robot);
avoid_obstacles  = new v_Avoid_va(2.0, 1.0, <B>detect_obstacles</B>);
</PRE>

In this example, a detect_obstacles node is created using 
the va_Obstacles_r class (the va_Obstacle_r class knows how to 
query the robot hardware
for information about obstacles).  Next an avoid_obstacles
node is generated by embedding the detect_obstacles node in a
v_Avoid_va object.  The lower-case letters before and after
the node names refer to the input and output types of the node;
these hints are helpful when configuring nodes.  More on that later.
<P>
Note that the embedding provides for code re-use.  We could,
for instance, avoid robots instead by embedding detect_robots
versus detect_obstacles in the v_Avoid_va node.
It is also possible to re-use instantiated nodes
by embedding them in several other nodes.
In this next example, detect_obstacle is imbedded in an avoid_obstacle
node and a swirl_obstacle node:
<P>
<PRE>
<B>detect_obstacles</B> = new va_Obstacles_r(abstract_robot);
avoid_obstacles  = new v_Avoid_va(2.0, 1.0, <B>detect_obstacles</B>);
swirl_obstacles  = new v_Swirl_va(2.0, 1.0, <B>detect_obstacles</B>, heading);
</PRE>

<P>
Nodes are combined or blended by embedding them in a blending node.
v_StaticWeightedSum_va is an example blending node class.
If you are familiar with motor schema theory,
this type node is used for the "sum and normalize" step of
schema and assemblage combining.
It takes an array of Nodes and an array of weights as input at
configuration time.  At runtime, it multiplies the output
of each embedded node by the associated weight or gain, then sums them.
The following statements generate a new
node, avoid_n_swirl, that is the average of its two embedded
nodes:
<P>
<PRE>
<b>avoid_n_swirl</b> = new v_StaticWeightedSum_va();<BR>
avoid_n_swirl.embedded[0]   = <b>avoid_obstacles</b>;<BR>
avoid_n_swirl.weights[0]    = 0.5;
avoid_n_swirl.embedded[1]   = <b>swirl_obstacles</b>;
avoid_n_swirl.weights[1]    = 0.5;
</PRE>
<P>

<b>Runtime</b><BR>

Once a Clay-based behavioral system has been specifed, it is
repeatedly called at runtime for it's present value, based
on the current situation of the robot.
The configuration is the entire behavioral system encapsulated in 
a single object.  
For convention, we usually call this object <b>configuration</b>.  
It is often useful to create separate configurations
for each actuator, as might
be the case with a Nomad 150 that has steering and turret actuators.
In this case we would call the configurations 
<b>steering_configuration</b> and <b>turret_configuration</b>.
<p>
At each timestep the configuration is activated through a call
to configuration.Value().  configuration.Value() implicitly
activates any embedded nodes through calls to their
Value() methods, and so a heirarchical top-down chain of
calls is initiated.  How do we avoid a computational explosion?
Several mechanisms are included in Clay to address this
potential problem.
<p>
First all the Value() methods take a timestamp as a parameter.  They 
remember the last time they were called, and if the timestamp 
has not increased,
they return the last computed value.  Thus if a node is reused
by embedding in several other nodes, it will only go to the
trouble of computing its value once per timestep.  To ensure
this, all nodes call embedded nodes with the timestamp they 
were passed.  The timestamp is never incremented by a node.
It is set at the highest level
by the object calling the configuration (either TBHard or
TBSim).
<p>
Second, Clay includes some node types that select rather than blend.
In a selection node, only one embedded sub-node is activated at a time,
thus fan-out calls are eliminated.
<P>

<b>Designing Your Own Nodes</b><BR>

Developing a new node is fairly easy.  There are two things to
consider first: what types of input will it require?
and what will its output type be?  Input is provided by
the Value() method of embedded nodes or by fixed parameters
passed to the constructor at initialization time.
Java type-checking ensures that we can only embed nodes whose
output types match the input type specified by the
parent node's constructor.
<p>
As mentioned above, input types for a node are specified by 
the constructor declaration.  The output type is specified by its Value()
definition.  You should implement your node by extending one
of the following classes, based on the desired output type for your
node:

<ul>
<LI><b>NodeBoolean</b>, the node outputs a boolean.
<LI><b>NodeDouble</b>, the node outputs a double.
<LI><b>NodeInt</b>, the node outputs an int.
<LI><b>NodeScalar</b>, the node can output an int, double or boolean,
		as requested by the caller.
<LI><b>NodeVec2</b>, the node outputs a 2-dimensional vector.
<LI><b>NodeVec2Array</b>, the node outputs an array of 2-dimensional vectors.
</UL>

Although Clay can certainly be utilized for other types of
behavioral paradigms, it specifically targets motor schema-based
control.  Several motor and perceptual schemas have already been
designed, and are included in the Clay distribution.
Motor schemas are usually NodeVec2s.  Perceptual schemas may
be NodeVec2s or NodeVec2Arrays depending on what sorts of
things they sense.  Perceptual features are typically NodeBooleans or
NodeInts.

Once you have selected the input and output types of your node, you
must implement the constructor and Value() methods.  Probably
the best way to get started is by looking at some of the exisiting
nodes for inspiration.  v_LinearAttraction_v and v_AvoidArray_va are
good examples.
<P>

<b>Naming Convention</b><BR>

To help make it easier for designers to determine which nodes are which,
we have developed a naming convention.  Each node class is named
as follows:

<PRE>
<i>{output type}_{name}_{embedded node 1 type}{embedded node 2 type}{...}</i>
</PRE>

The name is the name you give your node.  Variations that
provide slightly different outputs or use many instead of one
input are distinguished by the output and embedded type prefix
and suffixes.  Note that a node can only have one output type.
The types are given by one or two letter abbreviations as follows:

<table>
<tr><td>i</td><td>int</td></tr>
<tr><td>ia</td><td>int[]</td></tr>
<tr><td>d</td><td>double</td></tr>
<tr><td>da</td><td>double[]</td></tr>
<tr><td>v</td><td>Vec2</td></tr>
<tr><td>va</td><td>Vec2[]</td></tr>
<tr><td>b</td><td>boolean</td></tr>
<tr><td>ba</td><td>boolean[]</td></tr>
<tr><td>s</td><td>Scalar</td></tr>
<tr><td>sa</td><td>Scalar[]</td></tr>
<tr><td>r</td><td>robot - only valid as an input.</td></tr>
</table>

So a node named Avoid that takes an array of Vec2s as input and
outputs a single Vec2 would be called v_Avoid_va.
The name of the node should clearly and succintly indicate its
purpose (e.g. Obstacle, LinearAttraction).
Nodes taking a robot object as input usually provide some sort
of sensor output. va_Obstacles_r for example, outputs a list of detected
obstacles.

</body>
</html>
